'''
modbus是一种通用的传输通信协议，对于符合modbus协议的设备来说，都有一个设备编号，
然后遵循统一的modbus指令规则.所发送和接收的数据，按照指令归则，
由设备号+指令号+指令数据+校验数据，依次按二进制原始数据组合为一条数据帧，然后通过
串口或者网络传输到对方，对方接收后按照同样的规则解析出数据内容，执行有关的动作，
并给予同样满足规则的回复的数据帧，从而完成一次通信。
本设备使用基于RS485串口进行通信且符合modbus通信协议的基础通信模块来进行IO信息的输入和输出。
该模块自带8个IO端口，每个端口可以通过发送指令来进行配置以便作为输入或输出端口，每个端口要么
作为输出端口，要么作为输出端口。
该模块在出厂时，设备编号默认为2，所有端口均配置为输入型端口，因此需要预先进行配置才能满足实验要求。
该模块串口通信速率默认57600,校验规则为偶校验，数据位数为8位，停止位为1位。
'''
# 设备号+指令号+指令数据+校验数据
# 实现modbus通信帧中必须的数据校验的功能
# 该功能主要是作为数据帧的尾部添加从而组成完整的数据帧，
# 其实质功能就是对一段二进制数据data进行运算从而得到校验数据crc，
# 接收方收到连接在一起的data+crc后，同样对收到数据的data部分进行相同的校验，如果得到的crc相同，则认为数据完整
# 参数data为bytearray，返回值为bytearray
# def getModbusCrc(data:bytearray)

'''python有一个专门用于crc校验的库（crcmod），可以方便的完成CRC校验工作。
安装：pip3 install crcmod
以下是计算16位的crc校验，如需其他crc校验可以查看库的有关文档或在教程'''

import crcmod
import binascii

#需要学生来完成的函数getModbusCrc
def getModbusCrc(data:bytearray):
    #从crcmod模块获取一个校验函数
    crc16fun = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000)
    #调用这个校验函数得到一个16位的整数
    tmp=crc16fun(data)
    #将16位整数高地位逆向组合成一个btyearray并返回
    v= bytearray([tmp & 0xff,(tmp >> 8) & 0xff])
    print( "输入数据 %s ,附加校验后数据 %s" % (data.hex() ,data.hex()+v.hex() ))
    return v

#通过以下命令测试getModbusCrc
#按文档规则组成命令数据
data=bytearray.fromhex("02 04 00 04 00 01")
#获取校验校验
getModbusCrc(data)


'''
该基础通信模块的IO口功能(输入输出),通信速率，设备编号均为可配置的
通过查阅文档可以进行配置，在完成以上CRC校验函数的基础上，可以通过编成的方式
来取代串口调试工具来进行设备的配置和调试
#注意，设置的时候必须要让灰色信号线处于高电平位置方可设置成功
'''